#include <string>
#include <iostream>

using namespace std;

namespace shr
{
    class pizza
    {
    public:
        virtual void prepare() = 0;
        virtual void bake() = 0;
        virtual void cut() = 0;
        virtual void box() = 0;
        virtual const string type() = 0;
        virtual const string tag() = 0;
    
    protected:
        size_t _size;
    };

    class cheesePizza : public pizza
    {
    public:
        cheesePizza(const string tag = "")
            :_type("cheese"), _tag(tag)
        { }

        virtual void prepare()
        {
            cout << "cheese pizza prepare" << endl;
        }

        virtual void bake()
        {
            cout << "cheese pizza bake" << endl;
        }

        virtual void cut()
        {
            cout << "cheese pizza cut" << endl;
        }

        virtual void box()
        {
            cout << "cheese pizza box" << endl;
        }

        virtual const string type()
        {
            return _type;
        }

        virtual const string tag()
        {
            return _tag;
        }

    protected:
        string _type;
        string _tag;
    };

    class greekPizza : public pizza
    {
    public:
        greekPizza(const string tag = "")
            :_type("greek"), _tag(tag)
        { }

        virtual void prepare()
        {
            cout << "greek pizza prepare" << endl;
        }

        virtual void bake()
        {
            cout << "greek pizza bake" << endl;
        }

        virtual void cut()
        {
            cout << "greek pizza cut" << endl;
        }

        virtual void box()
        {
            cout << "greek pizza box" << endl;
        }

        virtual const string type()
        {
            return _type;
        }

        virtual const string tag()
        {
            return _tag;
        }

    protected:
        string _type;
        string _tag;
    };

/*---------------------------↑ 有关披萨种类的定义 ↑----------------------*/
/*---------------------------↓ 为披萨店而做的框架 ↓----------------------*/

    //对pizzaStore的重写：为披萨店而做的框架
    class pizzaStore
    {
    public:
        pizza* orderPizza(string type) //其他连锁披萨店只能使用pizzaStore的order方法
        {
            pizza* pz = createPizza(type);
            pz->prepare();
            pz->bake();
            pz->cut();
            pz->box();
            return pz;
        }
    
    protected:
        //将制作披萨的方法设计为纯虚函数，由各地加盟店根据风味进行
        virtual pizza* createPizza(string type) = 0;
    };

    class NYPizzaStore : public pizzaStore
    {
    public:
    
    protected:
        //制作纽约风味的披萨
        virtual pizza* createPizza(string type)
        {
            pizza* pz = nullptr;
            if(type == "cheese") {
                pz = new cheesePizza("NY");
            }
            else if(type == "greek") {
                pz = new greekPizza("NY");
            } else {}
            return pz;
        }
    };

    class ChicagoPizzaStore : public pizzaStore
    {
    public:
    
    protected:
        //制作芝加哥风味的披萨
        virtual pizza* createPizza(string type)
        {
            pizza* pz = nullptr;
            if(type == "cheese") {
                pz = new cheesePizza("Chicago");
            }
            else if(type == "greek") {
                pz = new greekPizza("Chicago");
            } else {}
            return pz;
        }
    };

    /*
    为pizza而做的框架
    */
    //将pizza实现为一个抽象类 具体实现由各类pizza进行覆盖
    // class pizza
    // {
    // public:
    //     virtual void prepare() = 0;
    //     virtual void bake() = 0;
    //     virtual void cut() = 0;
    //     virtual void box() = 0;
    //     virtual const string type() = 0;
    
    // protected:
    //     size_t _size;
    // };

    // //一个简单工厂
    // class simplePizzaFactor
    // {
    // public:
    //     pizza* orderPizza(string type)
    //     {
    //         pizza* pz = nullptr;
    //         if (type == "cheese") {
    //             pz = new cheesePizza();
    //         }
    //         else if (type == "greek") {
    //             pz = new greekPizza();
    //         } else { }
    //         return pz;
    //     }
    // };

    const string type(pizza* pz)
    {
        return pz->type();
    }

    const string tag(pizza* pz)
    {
        return pz->tag();
    }

    // //对披萨店的重写
    // class pizzaStore
    // {
    // public:
    //     pizzaStore()
    //     {
    //         simplePizzaFactor factor;
    //         _factor = factor;
    //     }

    //     pizza* orderPizza(string type)
    //     {
    //         pizza* pz = _factor.orderPizza(type);
    //         pz->prepare();
    //         pz->bake();
    //         pz->cut();
    //         pz->box();
    //         return pz;
    //     }

    // protected:
    //     simplePizzaFactor _factor;
    // };

    // class pizza
    // {
    // public:
    //     pizza(size_t size = 10)
    //         :_size(size)
    //     { }

    //     virtual const string type()
    //     {
    //         return "";
    //     }

    // protected:
    //     size_t _size;
    // };

    // class cheesePizza : public pizza
    // {
    // public:
    //     cheesePizza()
    //         :_type("cheese")
    //     { }

    //     virtual const string type()
    //     {
    //         return _type;
    //     }

    // protected:
    //     string _type;
    // };

    // class greekPizza : public pizza
    // {
    // public:
    //     greekPizza()
    //         :_type("greek")
    //     { }

    //     virtual const string type()
    //     {
    //         return _type;
    //     }

    // protected:
    //     string _type;
    // };
}